#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: bao
# @Date:   2017-01-16 11:59:53
# @Last Modified by:   bao
# @Last Modified time: 2017-05-01 14:25:32


class Flow(object):
    """docstring for flow"""

    def __init__(self):
        # Flow Id
        self.flowId = -1

        # Flow size
        self.flowSize = 0.0

        # Remain size
        self.remainSize = 0.0

        # Obtained bandwidth
        self.bw = 0.0

        # Start&End node id for this flow
        self.startId = -1
        self.endId = -1

        # Path links
        self.pathLength = 0
        self.pathLinkIds = []
        self.ocsPathLinkIds = []

        # Energy
        self.energy = 0.0

        # Start time
        self.startTime = 0.0

        # Update time: The time of last update of flow states
        self.updateTime = 0.0

        #
        self.finishSending = 0.0

        # Finish time
        self.finishTime = 0.0

        self.oracleFct = 0.0

        # Finish event
        self.finishEvent = 0

        # Job Id: this flow may be contained by a job
        # Each flow is only contained by one job and one
        # a job have many tasks, a task has many coflows,
        # a coflow has many flows.
        # a multicast flow has many flows.
        self.jobId = 0
        self.taskId = 0
        self.coflowId = 0
        self.mcastFlowId = 0
        self.subflowId = 0

        # Priority/Service
        self.priority = -1

        # Deadline
        self.deadline = -1
        self.remainTime = -1
        self.residualRate = -1.0

    def __repr__(self):
        return "flow_id:{!r}, src:{!r}, dst:{!r}, startTime:{!r}, flowSize:{!r}".format(self.flowId, self.startId,
                                                                                        self.endId, self.startTime,
                                                                                        self.flowSize)

    def SetFlowSize(self, size):
        self.flowSize = size
        self.remainSize = size

    def SetFlowDeadline(self, ddl):
        self.deadline = ddl
        self.remainTime = ddl

    def SerCBR(self, cbr):
        self.bw = cbr
        self.cbr = True

    def calculateFlowSlowdown(self):
        if self.finishTime < self.startTime:
            print "flow has negative fct"

        fct = (self.finishTime - self.startTime)
        slowdown = fct / self.oracleFct
        if slowdown >= 1:
            return slowdown
        elif slowdown < 0.999:
            print "flow has fct better than oracle"
        else:
            return 1.000000

    # Routing with give a list of nodes that this flow traverses
    # BuildPath() builds a path with pathNodeIds[:]
    def BuildPath(self, pathNodeIds):
        # Build path in node ids
        self.pathLinkIds = []
        # Build path in link ids
        # Append tuple of nodes as links.
        for i in range(len(pathNodeIds) - 1):
            self.pathLinkIds.append((pathNodeIds[i], pathNodeIds[i + 1]))


class MulticastFlow(object):
    """docstring for MultiFlow"""

    def __init__(self):
        self.flowId = -1
        self.srcToR = -1
        self.srcHost = -1
        self.dstToRs = {}
        self.dstHosts = {}
        self.flowSize = 0.0
        self.groupSize = 0
        self.startTime = 0.0
        self.finishTime = 0.0
        self.energy = 0.0
